package com.mofum.scope.spring.boot.registrar;

import com.mofum.scope.spring.boot.annotation.*;
import com.mofum.scope.spring.boot.scanner.DataBeanDefinitionScanner;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.StandardAnnotationMetadata;
import org.springframework.core.type.filter.AnnotationTypeFilter;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;

/**
 * 协议注册
 *
 * @author yumi@omuao.com
 * @since 2019-10-22
 **/
public class DataBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware, BeanFactoryAware {

    /**
     * Bean工厂
     */
    private BeanFactory beanFactory;

    /**
     * 资源加载器
     */
    private ResourceLoader resourceLoader;

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = beanFactory;
    }

    @Override
    public void setResourceLoader(ResourceLoader resourceLoader) {
        this.resourceLoader = resourceLoader;
    }

    @Override
    public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
        DataBeanDefinitionScanner scanner = new DataBeanDefinitionScanner(beanDefinitionRegistry);
        scanner.addIncludeFilter(new AnnotationTypeFilter(ScopeController.class));
        scanner.addIncludeFilter(new AnnotationTypeFilter(ScopeService.class));
        scanner.addIncludeFilter(new AnnotationTypeFilter(ScopeErrorHandler.class));
        scanner.addIncludeFilter(new AnnotationTypeFilter(ScopeAuthenticator.class));
        scanner.addIncludeFilter(new AnnotationTypeFilter(ScopeConverter.class));
        scanner.addIncludeFilter(new AnnotationTypeFilter(ScopeExtractor.class));
        scanner.setResourceLoader(resourceLoader);
    }

    /**
     * 从元数据中获取注解信息
     *
     * @param annotationMetadata 元数据
     * @return 注解信息
     */
    private Annotation[] getAnnotations(AnnotationMetadata annotationMetadata) {
        Annotation[] annotations = null;
        try {
            Field field = StandardAnnotationMetadata.class.getDeclaredField("annotations");
            field.setAccessible(true);
            annotations = (Annotation[]) field.get(annotationMetadata);
            field.setAccessible(false);
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        }
        return annotations;
    }

    public BeanFactory getBeanFactory() {
        return beanFactory;
    }

    public ResourceLoader getResourceLoader() {
        return resourceLoader;
    }
}